package com.zeyun.EasyOnlineShareCloud.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zeyun.EasyOnlineShareCloud.common.convention.exception.ServiceException;
import com.zeyun.EasyOnlineShareCloud.common.enums.ResultErrorCodeEnums;
import com.zeyun.EasyOnlineShareCloud.dao.entity.FileDO;
import com.zeyun.EasyOnlineShareCloud.dao.entity.RecordDO;
import com.zeyun.EasyOnlineShareCloud.dao.entity.UserDO;
import com.zeyun.EasyOnlineShareCloud.dao.mapper.FileMapper;
import com.zeyun.EasyOnlineShareCloud.dao.mapper.RecordMapper;
import com.zeyun.EasyOnlineShareCloud.dao.mapper.UserMapper;
import com.zeyun.EasyOnlineShareCloud.dto.req.admin.FileUpdateStatusReqDTO;
import com.zeyun.EasyOnlineShareCloud.dto.req.admin.UserAddReqDTO;
import com.zeyun.EasyOnlineShareCloud.dto.req.admin.UserEditReqDTO;
import com.zeyun.EasyOnlineShareCloud.dto.resp.admin.*;
import com.zeyun.EasyOnlineShareCloud.service.AdminService;
import com.zeyun.EasyOnlineShareCloud.utils.PasswordGenerator;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 管理员服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AdminServiceImpl implements AdminService {

	private final UserMapper userMapper;
	private final FileMapper fileMapper;
	private final RecordMapper recordMapper;

	@Override
	public DashboardRespDTO getDashboardData() {
		// 1. 获取用户总数
		LambdaQueryWrapper<UserDO> userQueryWrapper = new LambdaQueryWrapper<>();
		userQueryWrapper.eq(UserDO::getDelFlag, 0)
				.eq(UserDO::getRole, "user");
		Long userCount = userMapper.selectCount(userQueryWrapper);

		// 2. 获取文件总数
		LambdaQueryWrapper<FileDO> fileQueryWrapper = new LambdaQueryWrapper<>();
		fileQueryWrapper.eq(FileDO::getDelFlag, 0)
				.eq(FileDO::getStatus, "active");
		Long fileCount = fileMapper.selectCount(fileQueryWrapper);

		// 3. 获取今日上传数量
		LocalDateTime today = LocalDate.now().atStartOfDay();
		Date todayDate = Date.from(today.atZone(ZoneId.systemDefault()).toInstant());

		LambdaQueryWrapper<RecordDO> uploadQueryWrapper = new LambdaQueryWrapper<>();
		uploadQueryWrapper.eq(RecordDO::getGenre, "up")
				.ge(RecordDO::getCreateTime, todayDate);
		Long todayUploads = recordMapper.selectCount(uploadQueryWrapper);

		// 4. 获取今日下载数量
		LambdaQueryWrapper<RecordDO> downloadQueryWrapper = new LambdaQueryWrapper<>();
		downloadQueryWrapper.eq(RecordDO::getGenre, "down")
				.ge(RecordDO::getCreateTime, todayDate);
		Long todayDownloads = recordMapper.selectCount(downloadQueryWrapper);

		// 5. 获取上传/下载趋势数据（最近7天）
		DashboardRespDTO.TrendDataRespDTO trendData = getTrendData();

		// 6. 获取存储空间使用情况
		List<DashboardRespDTO.StorageDataRespDTO> storageData = getStorageData();

		// 7. 获取最近活动
		List<DashboardRespDTO.ActivityRespDTO> recentActivities = getRecentActivities();

		// 构建并返回响应DTO
		return DashboardRespDTO.builder()
				.userCount(userCount)
				.fileCount(fileCount)
				.todayUploads(todayUploads)
				.todayDownloads(todayDownloads)
				.trendData(trendData)
				.storageData(storageData)
				.recentActivities(recentActivities)
				.build();
	}

	/**
	 * 获取上传/下载趋势数据（最近7天）
	 *
	 * @return 趋势数据
	 */
	private DashboardRespDTO.TrendDataRespDTO getTrendData() {
		List<String> dates = new ArrayList<>();
		List<Long> uploads = new ArrayList<>();
		List<Long> downloads = new ArrayList<>();

		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd");
		LocalDate today = LocalDate.now();

		// 获取最近7天的日期
		for (int i = 6; i >= 0; i--) {
			LocalDate date = today.minusDays(i);
			dates.add(date.format(formatter));

			// 获取当天的上传数量
			LocalDateTime startOfDay = date.atStartOfDay();
			LocalDateTime endOfDay = date.plusDays(1).atStartOfDay();
			Date startDate = Date.from(startOfDay.atZone(ZoneId.systemDefault()).toInstant());
			Date endDate = Date.from(endOfDay.atZone(ZoneId.systemDefault()).toInstant());

			// 上传数量
			LambdaQueryWrapper<RecordDO> uploadWrapper = new LambdaQueryWrapper<>();
			uploadWrapper.eq(RecordDO::getGenre, "up")
					.ge(RecordDO::getCreateTime, startDate)
					.lt(RecordDO::getCreateTime, endDate);
			Long uploadCount = recordMapper.selectCount(uploadWrapper);
			uploads.add(uploadCount);

			// 下载数量
			LambdaQueryWrapper<RecordDO> downloadWrapper = new LambdaQueryWrapper<>();
			downloadWrapper.eq(RecordDO::getGenre, "down")
					.ge(RecordDO::getCreateTime, startDate)
					.lt(RecordDO::getCreateTime, endDate);
			Long downloadCount = recordMapper.selectCount(downloadWrapper);
			downloads.add(downloadCount);
		}

		// 构建并返回响应DTO
		return DashboardRespDTO.TrendDataRespDTO.builder()
				.dates(dates)
				.uploads(uploads)
				.downloads(downloads)
				.build();
	}

	/**
	 * 获取存储空间使用情况
	 *
	 * @return 存储空间使用情况
	 */
	private List<DashboardRespDTO.StorageDataRespDTO> getStorageData() {
		List<FileDO> files = fileMapper.selectList(null);

		// 按文件类型分组并计算总大小
		Map<String, Long> sizeByType = files.stream()
				.collect(Collectors.groupingBy(
						FileDO::getFileType,
						Collectors.summingLong(FileDO::getFileSize)
				));

		// 转换为前端需要的格式（MB为单位）
		List<DashboardRespDTO.StorageDataRespDTO> result = new ArrayList<>();
		sizeByType.forEach((type, size) -> {
			String typeName = getFileTypeName(type);
			double sizeMB = size / (1024.0 * 1024.0); // 转换为MB
			double roundedSize = Math.round(sizeMB * 100) / 100.0; // 保留两位小数

			result.add(DashboardRespDTO.StorageDataRespDTO.builder()
					.name(typeName)
					.value(roundedSize)
					.build());
		});

		return result;
	}

	/**
	 * 获取文件类型名称
	 *
	 * @param type 文件类型
	 * @return 文件类型名称
	 */
	private String getFileTypeName(String type) {
		return switch (type) {
			case "document" -> "文档";
			case "image" -> "图片";
			case "video" -> "视频";
			case "audio" -> "音频";
			case "archive" -> "压缩包";
			default -> "其他";
		};
	}

	/**
	 * 获取最近活动
	 *
	 * @return 最近活动
	 */
	private List<DashboardRespDTO.ActivityRespDTO> getRecentActivities() {
		// 获取最近20条记录
		LambdaQueryWrapper<RecordDO> wrapper = new LambdaQueryWrapper<>();
		wrapper.orderByDesc(RecordDO::getCreateTime)
				.last("LIMIT 20");
		List<RecordDO> records = recordMapper.selectList(wrapper);

		// 获取用户信息和文件信息
		Map<String, UserDO> userMap = new HashMap<>();
		Map<String, FileDO> fileMap = new HashMap<>();

		// 收集所有需要查询的用户ID和文件ID
		Set<String> userIds = records.stream()
				.map(RecordDO::getUserId)
				.filter(Objects::nonNull)
				.collect(Collectors.toSet());

		Set<String> fileIds = records.stream()
				.map(RecordDO::getFileId)
				.filter(Objects::nonNull)
				.collect(Collectors.toSet());

		// 批量查询用户和文件信息
		if (!userIds.isEmpty()) {
			LambdaQueryWrapper<UserDO> userWrapper = new LambdaQueryWrapper<>();
			userWrapper.in(UserDO::getId, userIds);
			List<UserDO> users = userMapper.selectList(userWrapper);
			userMap = users.stream().collect(Collectors.toMap(UserDO::getId, user -> user));
		}

		if (!fileIds.isEmpty()) {
			LambdaQueryWrapper<FileDO> fileWrapper = new LambdaQueryWrapper<>();
			fileWrapper.in(FileDO::getId, fileIds);
			List<FileDO> files = fileMapper.selectList(fileWrapper);
			fileMap = files.stream().collect(Collectors.toMap(FileDO::getId, file -> file));
		}

		// 转换为前端需要的格式
		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
		List<DashboardRespDTO.ActivityRespDTO> result = new ArrayList<>();

		for (RecordDO record : records) {
			// 时间
			LocalDateTime createTime = LocalDateTime.ofInstant(
					record.getCreateTime().toInstant(),
					ZoneId.systemDefault());
			String formattedTime = createTime.format(formatter);

			// 用户
			String userId = record.getUserId();
			UserDO user = userMap.get(userId);
			String username = user != null ? user.getUsername() : "未知用户";

			// 操作
			String action = getActionName(record.getGenre());

			// 详情
			String fileId = record.getFileId();
			FileDO file = fileMap.get(fileId);
			String details = file != null ? file.getFileName() : "未知文件";

			// 构建活动DTO并添加到结果列表
			result.add(DashboardRespDTO.ActivityRespDTO.builder()
					.time(formattedTime)
					.user(username)
					.ip(record.getIp())
					.action(action)
					.details(details)
					.build());
		}

		return result;
	}

	/**
	 * 获取操作名称
	 *
	 * @param genre 操作类型
	 * @return 操作名称
	 */
	private String getActionName(String genre) {
		return switch (genre) {
			case "up" -> "上传文件";
			case "down" -> "下载文件";
			case "delete" -> "删除文件";
			default -> "未知操作";
		};
	}

	@Override
	public Page<UserListRespDTO> getUserListByPage(int pageNum, int pageSize) {
		// 分页对象
		Page<UserDO> page = new Page<>(pageNum, pageSize);

		// 查询条件
		LambdaQueryWrapper<UserDO> userWrapper = new LambdaQueryWrapper<>();
		userWrapper.orderByDesc(UserDO::getCreateTime);

		// 执行分页查询
		Page<UserDO> userPage = userMapper.selectPage(page, userWrapper);

		// 将分页结果中的 records 转换为 DTO
		List<UserListRespDTO> dtoList = userPage.getRecords().stream().map(user -> UserListRespDTO.builder()
				.id(user.getId())
				.username(user.getUsername())
				.email(user.getEmail())
				.role(user.getRole())
				.status(user.getStatus())
				.createTime(user.getCreateTime())
				.updateTime(user.getUpdateTime())
				.build()).collect(Collectors.toList());

		// 返回 Page<UserListRespDTO>
		Page<UserListRespDTO> result = new Page<>();
		result.setCurrent(userPage.getCurrent());
		result.setSize(userPage.getSize());
		result.setTotal(userPage.getTotal());
		result.setRecords(dtoList);

		return result;
	}


	@Override
	public ResetPasswordRespDTO resetUserPassword(String userId) {
		// 查询用户
		UserDO user = userMapper.selectById(userId);
		if (user == null || user.getDelFlag() == 1) {
			throw new RuntimeException("用户不存在");
		}

		// 生成新密码
		String newPassword = PasswordGenerator.generateRandomPassword(6);

		// 更新用户密码
		user.setPassword(newPassword);
		userMapper.updateById(user);

		// 返回重置密码结果
		return ResetPasswordRespDTO.builder()
				.userId(user.getId())
				.username(user.getUsername())
				.newPassword(newPassword)
				.build();
	}

	@Override
	public void deleteUser(String userId) {
		// 查询用户
		UserDO user = userMapper.selectById(userId);
		if (user == null || user.getDelFlag() == 1) {
			throw new ServiceException(ResultErrorCodeEnums.DATABASE_QUERY_ERROR);
		}
		try {
			userMapper.deleteById(userId);
		} catch (Exception e) {
			throw new ServiceException(ResultErrorCodeEnums.DATABASE_UPDATE_ERROR);
		}
	}

	@Override
	public UserAddRespDTO addUser(UserAddReqDTO requestParam) {
		UserDO user = UserDO.builder()
				.username(requestParam.getUsername())
				.password(requestParam.getPassword())
				.email(requestParam.getEmail())
				.role(requestParam.getRole())
				.status(requestParam.getStatus())
				.build();
		try {
			// 保存到数据库
			userMapper.insert(user);
			log.info("新用户注册成功: {}", user.getUsername());
			return BeanUtil.toBean(user, UserAddRespDTO.class);
		} catch (Exception e) {
			log.error("用户注册失败", e);
			throw new ServiceException("用户注册失败: " + e.getMessage());
		}
	}


	@Override
	public void editUser(UserEditReqDTO requestParam) {
		// 1. 检查用户是否存在
		UserDO userDO = userMapper.selectById(requestParam.getId());
		if (userDO == null) {
			throw new ServiceException(ResultErrorCodeEnums.USER_NOT_FOUND);
		}

		// 2. 更新用户信息
		LambdaUpdateWrapper<UserDO> updateWrapper = new LambdaUpdateWrapper<>();
		updateWrapper.eq(UserDO::getId, requestParam.getId())
				.set(UserDO::getUsername, requestParam.getUsername())
				.set(UserDO::getEmail, requestParam.getEmail())
				.set(UserDO::getRole, requestParam.getRole());

		userMapper.update(null, updateWrapper);
	}

	/**
	 * 分页获取文件列表
	 *
	 * @param pageNum  页码
	 * @param pageSize 每页大小
	 * @param fileName 文件名（可选）
	 * @param fileType 文件类型（可选）
	 * @param status   状态（可选）
	 * @return 文件列表分页数据
	 */
	@Override
	public Page<FileRespDTO> getFileListByPage(int pageNum, int pageSize,
											   String fileName, String fileType,
											   String status, String auditStatus, String sortBy) {
		// 1. 构建查询条件
		LambdaQueryWrapper<FileDO> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(FileDO::getDelFlag, 0);

		// 2. 添加可选过滤条件
		if (StrUtil.isNotBlank(fileName)) {
			queryWrapper.like(FileDO::getFileName, fileName);
		}
		if (StrUtil.isNotBlank(fileType)) {
			queryWrapper.eq(FileDO::getFileType, fileType);
		}
		if (StrUtil.isNotBlank(status)) {
			queryWrapper.eq(FileDO::getStatus, status);
		}
		if (StrUtil.isNotBlank(auditStatus)) {
			queryWrapper.eq(FileDO::getAuditStatus, auditStatus);
		}

		// 3. 处理排序参数
		if (StrUtil.isNotBlank(sortBy)) {
			// 解析排序字段和排序方向
			String[] sortParams = sortBy.split("-");
			if (sortParams.length == 2) {
				String field = sortParams[0];
				String direction = sortParams[1];
				
				// 根据字段名映射到数据库字段
				switch (field) {
					case "uploadTime":
						if ("desc".equals(direction)) {
							queryWrapper.orderByDesc(FileDO::getCreateTime);
						} else {
							queryWrapper.orderByAsc(FileDO::getCreateTime);
						}
						break;
					case "fileSize":
						if ("desc".equals(direction)) {
							queryWrapper.orderByDesc(FileDO::getFileSize);
						} else {
							queryWrapper.orderByAsc(FileDO::getFileSize);
						}
						break;
					case "downloads":
						if ("desc".equals(direction)) {
							queryWrapper.orderByDesc(FileDO::getDownloadCount);
						} else {
							queryWrapper.orderByAsc(FileDO::getDownloadCount);
						}
						break;
					default:
						// 默认按创建时间降序
						queryWrapper.orderByDesc(FileDO::getCreateTime);
				}
			} else {
				// 默认按创建时间降序
				queryWrapper.orderByDesc(FileDO::getCreateTime);
			}
		} else {
			// 默认按创建时间降序
			queryWrapper.orderByDesc(FileDO::getCreateTime);
		}

		// 4. 执行分页查询
		Page<FileDO> filePage = new Page<>(pageNum, pageSize);
		Page<FileDO> fileDoPage = fileMapper.selectPage(filePage, queryWrapper);

		// 5. 转换为DTO对象
		Page<FileRespDTO> resultPage = new Page<>(fileDoPage.getCurrent(), fileDoPage.getSize(),
				fileDoPage.getTotal());

		if (fileDoPage.getRecords().isEmpty()) {
			resultPage.setRecords(Collections.emptyList());
			return resultPage;
		}

		// 6. 获取上传者信息
		List<String> uploaderIds = fileDoPage.getRecords().stream()
				.map(FileDO::getUploaderId)
				.collect(Collectors.toList());

		Map<String, String> uploaderMap = new HashMap<>();
		if (!uploaderIds.isEmpty()) {
			LambdaQueryWrapper<UserDO> userQueryWrapper = new LambdaQueryWrapper<>();
			userQueryWrapper.in(UserDO::getId, uploaderIds);
			List<UserDO> users = userMapper.selectList(userQueryWrapper);

			uploaderMap = users.stream()
					.collect(Collectors.toMap(
							UserDO::getId,
							UserDO::getUsername,
							(existing, replacement) -> existing
					));
		}

		// 7. 构建结果集
		Map<String, String> finalUploaderMap = uploaderMap;
		List<FileRespDTO> fileRespList = fileDoPage.getRecords().stream().map(fileDO -> {
			FileRespDTO fileRespDTO = BeanUtil.copyProperties(fileDO, FileRespDTO.class);
			fileRespDTO.setUploaderName(finalUploaderMap.getOrDefault(fileDO.getUploaderId(), "未知用户"));
			return fileRespDTO;
		}).collect(Collectors.toList());

		resultPage.setRecords(fileRespList);
		return resultPage;
	}

	/**
	 * 更新文件状态
	 *
	 * @param requestParam 文件状态更新请求参数
	 */
	@Override
	public void updateFileStatus(FileUpdateStatusReqDTO requestParam) {
		// 1. 检查文件是否存在
		FileDO fileDO = fileMapper.selectById(requestParam.getFileId());
		if (fileDO == null) {
			throw new ServiceException(ResultErrorCodeEnums.DATA_NOT_FOUND);
		}

		// 2. 更新文件状态
		LambdaUpdateWrapper<FileDO> updateWrapper = new LambdaUpdateWrapper<>();
		updateWrapper.eq(FileDO::getId, requestParam.getFileId());

		if (StrUtil.isNotBlank(requestParam.getStatus())) {
			updateWrapper.set(FileDO::getStatus, requestParam.getStatus());
		}

		if (StrUtil.isNotBlank(requestParam.getAuditStatus())) {
			updateWrapper.set(FileDO::getAuditStatus, requestParam.getAuditStatus());
			updateWrapper.set(FileDO::getAuditTime, new Date());

			if (StrUtil.isNotBlank(requestParam.getAuditRemark())) {
				updateWrapper.set(FileDO::getAuditRemark, requestParam.getAuditRemark());
			}
		}

		if (StrUtil.isNotBlank(requestParam.getFileName())) {
			updateWrapper.set(FileDO::getFileName, requestParam.getFileName());
			updateWrapper.set(FileDO::getAccessCode, requestParam.getAccessCode());
			updateWrapper.set(FileDO::getStatus, requestParam.getStatus());
			updateWrapper.set(FileDO::getAuditStatus, requestParam.getAuditStatus());
		}

		try {
			fileMapper.update(null, updateWrapper);
		} catch (Exception e) {
			log.error("文件状态更新失败", e);
			throw new ServiceException(ResultErrorCodeEnums.DATABASE_UPDATE_ERROR);
		}
	}

	/**
	 * 删除文件
	 *
	 * @param fileId 文件ID
	 */
	@Override
	public void deleteFile(String fileId) {
		// 1. 检查文件是否存在
		FileDO fileDO = fileMapper.selectById(fileId);
		if (fileDO == null) {
			throw new ServiceException(ResultErrorCodeEnums.DATA_NOT_FOUND);
		}

		// 2. 逻辑删除文件
		LambdaUpdateWrapper<FileDO> updateWrapper = new LambdaUpdateWrapper<>();
		updateWrapper.eq(FileDO::getId, fileId)
				.set(FileDO::getDelFlag, 1);

		fileMapper.update(null, updateWrapper);

		// 3. 物理删除文件（可选，根据业务需求决定是否需要）
		// TODO: 物理删除文件的逻辑，可以调用文件服务进行删除
	}

}